// 设置 HTTP 响应
import {
  ContentType,
  Controller,
  Get,
  HttpCode,
  Inject,
  SetHeader,
} from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';

@Controller('/api/controller/http/response')
export class HomeController {
  @Inject()
  ctx: Context;

  /**
   * 设置返回值
   * 绝大多数的数据都是通过 body 发送给请求方的，和请求中的 body 一样，在响应中发送的 body，也需要有配套的 Content-Type 告知客户端如何对数据进行解析。
   *
   * 作为一个 RESTful 的 API 接口 controller，我们通常会返回 Content-Type 为 application/json 格式的 body，内容是一个 JSON 字符串。
   * 作为一个 html 页面的 controller，我们通常会返回 Content-Type 为 text/html 格式的 body，内容是 html 代码段。
   * 在 Midway 中你可以简单的使用 return 来返回数据。
   */
  @Get('/setResponseVal')
  async setResponseVal() {
    // 返回字符串
    // return "Hello Midwayjs!"

    // 返回 json
    // return {
    //   a: 1,
    //   b: 2,
    // }

    // 返回 html
    // return '<html><h1>Hello</h1></html>'

    // 返回 stream

    const fs = require('fs');
    return fs.createReadStream('./good.png');
  }

  /**
   * 也可以使用 koa 原生的 API。
   * :::caution
   * 注意：ctx.body 是 ctx.response.body 的简写，不要和 ctx.request.body 混淆了。
   * :::
   */
  @Get('/setResponseValWithKoaApi')
  async setResponseValWithKoaApi() {
    // 返回字符串
    this.ctx.body = 'Hello Midwayjs!';

    // 返回 json
    this.ctx.body = {
      a: 1,
      b: 2,
    };

    // 返回 html
    this.ctx.body = '<html><h1>Hello</h1></html>';

    // 返回 stream
    const fs = require('fs');
    this.ctx.body = fs.createReadStream('./good.png');
  }

  /**
   * 设置状态码
   * 默认情况下，响应的状态码总是200，我们可以通过在处理程序层添加 @HttpCode 装饰器或者通过 API 来轻松更改此行为。
   *
   * 当发送错误时，如 4xx/5xx，可以使用 异常处理 抛出错误的方式实现。
   *
   * 示例：使用装饰器
   */
  @Get('/setResponseCode')
  @HttpCode(201)
  async setResponseCode() {
    return 'Hello Midwayjs!';
  }

  /**
   * 示例：使用 API
   * :::info 状态码不能在响应流关闭后（response.end之后）修改。 :::
   */
  @Get('/setResponseCodeWithApi')
  async setResponseCodeWithApi() {
    this.ctx.status = 201;
    // ...
    return 'Hello Midwayjs!';
  }

  /**
   * 设置响应头
   * Midway 提供 @SetHeader 装饰器或者通过 API 来简单的设置自定义响应头。
   *
   * 示例：使用装饰器
   */
  @Get('/setResponseHeader')
  @SetHeader('x-bbb', '123')
  async setResponseHeader() {
    return 'Hello Midwayjs!';
  }

  /**
   * 当有多个响应头需要修改的时候，你可以直接传入对象。
   */
  @Get('/setResponseHeaders')
  @SetHeader({
    'x-bbb': '123',
    'x-ccc': '234',
  })
  async setResponseHeaders() {
    return 'Hello Midwayjs!';
  }

  /**
   * 示例：使用 API
   * :::info 响应头不能在响应流关闭后（response.end之后）修改。 :::
   */
  @Get('/setResponseHeadersWithApi')
  async setResponseHeadersWithApi() {
    this.ctx.set('x-bbb', '123');
    // ...
  }

  /**
   * 响应类型
   * 虽然浏览器会自动根据内容判断最佳的响应内容，但是我们经常会碰到需要手动设置的情况。
   * 我们也提供了 @ContentType 装饰器用于设置响应类型。
   *
   * 此外，也可以通过 API 来设置。
   *
   * 示例：使用装饰器
   */
  @Get('/responseWithContentType')
  @ContentType('html')
  async responseWithContentType() {
    return '<body>hello world</body>';
  }

  /**
   * 示例：使用 API
   * :::info 响应类型不能在响应流关闭后（response.end之后）修改。 :::
   */
  @Inject()
  ctx2: Context;

  @Get('/responseWithContentTypeWithApi')
  async responseWithContentTypeWithApi() {
    this.ctx.type = 'html';
    // ...
  }
}
